﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization.Formatters.Binary;
using System.Text;
using System.Threading.Tasks;

namespace csharp_file
{
    class Program
    {
        // BinaryFormatter Serialzation
        [Serializable]
        struct StructData{
            public int intValue1;
            public bool boolValue1;
            public String stringValue1;
        }
        
        static void Main(string[] args)
        {
            ConsoleKeyInfo input_mode;

            do
            {
                fnPrintMode();
                input_mode = Console.ReadKey();
                Console.WriteLine();

                switch (input_mode.Key)
                {
                    case ConsoleKey.D1:
                    case ConsoleKey.NumPad1:
                        fnByteArrayMode();
                        break;
                    case ConsoleKey.D2:
                    case ConsoleKey.NumPad2:
                        fnBinaryMode();
                        break;
                    case ConsoleKey.D3:
                    case ConsoleKey.NumPad3:
                        fnSerializeMode();
                        break;
                    case ConsoleKey.D4:
                    case ConsoleKey.NumPad4:
                        fnTextMode();
                        break;
                }
            } while (input_mode.Key != ConsoleKey.Q);

            Console.Write("press any key...");
            Console.ReadKey();
        }

        static void fnPrintMode()
        {
            Console.WriteLine("1. byte array");
            Console.WriteLine("2. binary");
            Console.WriteLine("3. serialize");
            Console.WriteLine("4. text");
            Console.WriteLine("q. quit");
        }

        static void fnTextMode()
        {
            Console.Write("input text: ");
            String input_text = Console.ReadLine();

            fnTextWrite(input_text);
            String readData = fnTextRead();

            Console.WriteLine(readData);
        }

        static void fnTextWrite(String data)
        {
            using (StreamWriter streamWriter = new StreamWriter(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\text.txt"))
            {
                streamWriter.Write(data);
            }
        }

        static String fnTextRead()
        {
            String rtn;
            
            using (StreamReader streamReader = new StreamReader(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\text.txt"))
            {
                rtn = streamReader.ReadToEnd();
            }

            return rtn;
        }

        static void fnSerializeMode()
        {
            StructData data;
            data.intValue1 = 1;
            data.boolValue1 = true;
            data.stringValue1 = "my string";

            fnSerializeWrite(data);
            StructData readData = fnSerializeRead();

            foreach (FieldInfo field in readData.GetType().GetFields())
            {
                Console.WriteLine(field.ToString() + ": " + field.GetValue(readData));
            }
        }

        static void fnSerializeWrite(StructData data)
        {
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            using(FileStream fileStream = File.OpenWrite(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\serialize.txt"))
            {
                binaryFormatter.Serialize(fileStream, data);
            }
        }

        static StructData fnSerializeRead()
        {
            StructData rtn;
            
            BinaryFormatter binaryFormatter = new BinaryFormatter();
            using (FileStream fileStream = File.OpenRead(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\serialize.txt"))
            {
                rtn = (StructData)binaryFormatter.Deserialize(fileStream);
            }

            return rtn;
        }

        static void fnBinaryMode()
        {
            StructData data;
            data.intValue1 = 1;
            data.boolValue1 = true;
            data.stringValue1 = "my string";

            fnBinaryWrite(data);
            StructData readData = fnBinaryRead();

            foreach(FieldInfo field in readData.GetType().GetFields())
            {
                Console.WriteLine(field.ToString() + ": " + field.GetValue(readData));
            }
        }

        static void fnBinaryWrite(StructData data)
        {
            using(FileStream fileStream = File.OpenWrite(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\binary.txt"))
            {
                using(BinaryWriter binaryWriter = new BinaryWriter(fileStream))
                {
                    binaryWriter.Write(data.intValue1);
                    binaryWriter.Write(data.boolValue1);
                    binaryWriter.Write(data.stringValue1);

                    binaryWriter.Flush();
                    fileStream.Flush();
                }
            }
        }

        static StructData fnBinaryRead()
        {
            StructData rtn;
            
            using (FileStream fileStream = File.OpenRead(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\binary.txt"))
            {
                using (BinaryReader binaryReader = new BinaryReader(fileStream))
                {
                    rtn.intValue1 = binaryReader.ReadInt32();
                    rtn.boolValue1 = binaryReader.ReadBoolean();
                    rtn.stringValue1 = binaryReader.ReadString();
                }
            }

            return rtn;
        }

        static void fnByteArrayMode()
        {
            byte[] byteData = new byte[] { 1, 2 };
            fnByteArrayWrite(byteData);
            byte[] readData = fnByteArrayRead();

            Console.WriteLine(BitConverter.ToString(readData));
        }

        static void fnByteArrayWrite(byte[] data)
        {
            FileStream fileStream = new FileStream(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\bytearray.txt", FileMode.Create, FileAccess.Write);
            fileStream.Write(data, 0, data.Length);
            fileStream.Flush();
            fileStream.Close();
        }

        static byte[] fnByteArrayRead()
        {
            byte[] rtn;
            
            using (FileStream fileStream = File.OpenRead(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + @"\bytearray.txt"))
            {
                rtn = new byte[fileStream.Length];
                fileStream.Read(rtn, 0, Convert.ToInt32(fileStream.Length));
            }
            return rtn;
        }
    }
}
